/*
 * logger.c
 *
 *  Created on: 03/mag/2014
 *      Author: kappa
 */


#include "logger.h"

#ifdef _WIN32
static void * logfilehandle = NULL;
static struct tm *nowstime_file = NULL;
static struct tm *nowstime = NULL;
#endif

/************************************************************************
 * @function 		: initLogger										*
 * @descr			: Inizializza un file di log nella cartella indicata* 
 *					  dalla costante LOG_FOLDER. L'handler del file di  *
 *					  log � salvato nel puntatore logfilehandle.		*
 *					  La gestione degli errori � demandata alla libreria* 
 *					  errors.									 		*
 ************************************************************************/
void initLogger(){
#ifdef _WIN32
	char ** errparams;
	time_t now = time(NULL);
	nowstime = gmtime(&now);

	if (!SetCurrentDirectory(LOG_FOLDER)){
		createDir(LOG_FOLDER);
		if (!SetCurrentDirectory(LOG_FOLDER)){
			errparams = (char**) getMemory(1,PCHAR_TYPE);
			errparams[0] = LOG_FOLDER;
			notifyError(ERR_DIR_OPEN, errparams,1,1);
		}
	}

	if(isRotateLog() == 1){
		rotateLog();
	}
#else
	openlog(LOG_ID, LOG_PID, LOG_MAIL);
#endif
}

#ifdef _WIN32
/************************************************************************
 * @function 		: isrotatelog										*
 * @descr			: Verifica se � necessario chiudere il file di log	* 
 *					  attuale ed aprirne uno nuovo in base ad una		*
 *					  politica di turnazione definita sul cambio data.	* 
 * @return			: 1 se � necessario cambiare file, -1 altrimenti.	*
 ************************************************************************/
int isRotateLog(){

	if(nowstime_file == NULL)return 1;
	if(nowstime->tm_year > nowstime_file->tm_year){
		return 1;
	}
	else if(nowstime->tm_year == nowstime_file->tm_year){
		if(nowstime->tm_mon  > nowstime_file->tm_mon){
			return 1;
		}
		else if(nowstime->tm_mon == nowstime_file->tm_mon){
			if(nowstime->tm_mday > nowstime_file->tm_mday){
				return 1;
			}
			else return -1;
		}
		else return -1;
	}
	return -1;
}
#endif

#ifdef _WIN32
/************************************************************************
 * @function 		: rotatelog											*
 * @descr			: Chiude il filehandler corrente e ne apre uno nuovo*
 *					  per la nuova data. Aggiorna il puntatore			*
 *					  nowstime_file	con i riferimenti temporali al nuovo* 
 *					  file												* 
 ************************************************************************/
void rotateLog(void){
	char * filename = NULL;
	int isnewfile = 0;
	if(logfilehandle != NULL && logfilehandle != INVALID_HANDLE_VALUE){
			closeFile(logfilehandle);
	}
	filename = (char *)getMemory(256,CHAR_TYPE);
	memset(filename,'\0',256);
	/*Creo la stringa con il path per il nuovo file di log*/
	sprintf(filename,"log%d-%d-%d.log",(1900+nowstime->tm_year), nowstime->tm_mon+1, nowstime->tm_mday);
	logfilehandle = openOrCreateFile(filename, WRITE, &isnewfile);
	nowstime_file = nowstime;
}
#endif
/************************************************************************
 * @function 		: log												*
 * @descr			: Scrive un messaggio sul file di log.				* 
 ************************************************************************/
void logMessage(LEVEL level, char *message){

	char* buf = NULL;
	int priority = -1, bufsize = 0;
#ifdef _WIN32
	time_t now = 0;
#endif
	

if(message != NULL){

#ifdef _WIN32
		now = time(NULL);
		strcat (buf, ctime(&now));
		strcat (buf," -- ");
#endif
		switch(level){
			case INFO_LEV:
				bufsize += strlen(INFO_HEAD)+strlen(message)+1;
				buf = (char *)getMemory(bufsize,CHAR_TYPE);
				memset(buf, '\0',bufsize);
				strcat(buf,INFO_HEAD);
				break;

			case WARN_LEV:
				bufsize += strlen(WARN_HEAD)+strlen(message)+1;
				buf = (char *)getMemory(bufsize,CHAR_TYPE);
				memset(buf, '\0',bufsize);
				strcat(buf,WARN_HEAD);
				break;

			case ERR_LEV:
				bufsize += strlen(ERR_HEAD)+strlen(message)+1;
				buf = (char *)getMemory(bufsize,CHAR_TYPE);
				memset(buf, '\0',bufsize);
				strcat(buf,ERR_HEAD);
				break;

			case DBG_LEV:
				bufsize += strlen(DBG_HEAD)+strlen(message)+1;
				buf = (char *)getMemory(bufsize,CHAR_TYPE);
				memset(buf, '\0',bufsize);
				strcat(buf,DBG_HEAD);
				break;

			default: break;
		}
		strcat(buf,message);
		//buf[bufsize-3] = '\r';

#ifdef _WIN32

		if(isRotateLog() == 1){
			rotateLog();
		}
		//LockFileEx(logfilehandle,LOCKFILE_EXCLUSIVE_LOCK,0,0,0,NULL);
		writeFile(logfilehandle,buf);
		//UnlockFileEx(logfilehandle,0,0,0,NULL);
#else
		/*!!! WARNING: In *NIX se i commenti sono multilinea si deve aggiungere
		 * la seguente linea in /etc/rsyslog.conf e riavviare il demone syslogd.
		 * $EscapeControlCharactersOnReceive off
		 * Senza questa impostazione i caratteri di escape non verrano considerati e saranno scritti come #<ASCII CODE>
		 * */
		priority = decodeLevelToPriority(level);
		syslog( priority | LOG_MAIL, "%s", buf);//decodeLevelToPriority(level)|
#endif
		if(buf != NULL){
			free(buf);
			buf = NULL;
		}
	}
}

#ifndef _WIN32
int decodeLevelToPriority(LEVEL level){
	int priority = -1;
	switch(level){

	case INFO_LEV:
		priority = LOG_INFO;
		break;

	case WARN_LEV:
		priority = LOG_WARNING;
		break;

	case ERR_LEV:
		priority = LOG_ERR;
		break;

	case DBG_LEV:
		priority = LOG_DEBUG;
		break;

	default:
		priority = LOG_INFO;
		break;
	}

	return priority;
}
#endif

/************************************************************************
 * @function 		: closelogger										*
 * @descr			: chiude l'handler del file di log e imposta a NULL	* 
 *					  il puntatore logfilehandle.						* 
 ************************************************************************/
void closeLogger(){

#ifdef _WIN32
	//LockFileEx(logfilehandle, LOCKFILE_EXCLUSIVE_LOCK,0,0,0,NULL);
	closeFile(logfilehandle);
	logfilehandle = NULL;
	//UnlockFileEx(logfilehandle,0,0,0,NULL);
#else
	closelog();
#endif
}
